package com.lsu.app.controller.Teacher;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lsu.app.bean.*;
import com.lsu.app.config.target.RequestRoles;
import com.lsu.app.exception.RolePermissionException;
import com.lsu.app.service.*;
import com.lsu.app.tool.R;
import com.lsu.app.tool.uploadUtil;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @author hjj
 * @date 2023/10/16 18:57
 */
@RestController
@Slf4j
@CrossOrigin
@RequestMapping("/teLs")
public class TeLessonController {
    @Value("${web.upload-path}")
    private String uploadPath;
    private final LogService logservice;
    private final CollectService collectService;
    private final CourseScoreService scoreService;
    private final PraiseService praiseService;
    private final CourseService courseService;

    private final ResourceService resourceService;
    private final CommentService commentService;

    private final KindService kindService;
    private final TalkService talkService;
    @Autowired
    private HttpServletRequest request;

    public TeLessonController(LogService logservice, CollectService collectService, CourseScoreService scoreService, PraiseService praiseService, CourseService courseService, ResourceService resourceService, CommentService commentService, KindService kindService, TalkService talkService) {
        this.logservice = logservice;
        this.collectService = collectService;
        this.scoreService = scoreService;
        this.praiseService = praiseService;
        this.courseService = courseService;

        this.resourceService = resourceService;
        this.commentService = commentService;

        this.kindService = kindService;
        this.talkService = talkService;
    }

    @RequestRoles({"teacher"})
    @GetMapping("/getAllCourse")
    @ApiOperation("a获取教师所有课程[分页]")
    public R<Page<Course>> getAllCourse(
            @ApiParam("当前页")@RequestParam("pageCur") Integer pageCur,
            @ApiParam("页码")@RequestParam("pageSize") Integer pageSize
    ){
        Page<Course> list = courseService.page(new Page<>(pageCur,pageSize),new LambdaQueryWrapper<Course>().eq(Course::getTeacherId,request.getSession().getAttribute("id")).orderByDesc(Course::getUpdateTime));
        if(list.getTotal()<1){
            return R.err("该教师未创建课程");
        }
        for (Course course : list.getRecords()) {
            course.setCoverImgUrl(resourceService.getCoverImgUrlByCourseId(course.getId()));
            course.setResponds(commentService.getCountByTypeAndLinkId(1,course.getId()));
            course.setKindName(kindService.getValueByCourseId(course.getId()));
            String teacher = courseService.getTeacherNameByTeacherId(course.getTeacherId());
            course.setTeacherName(teacher!=null?teacher:"教师不存在");
        }
        return R.success(list);
    }

    @RequestRoles({"teacher"})
    @GetMapping("/getVideos")
    @ApiOperation("b获取课程下的所有视频")
    public R<List<Resource>> getVideosByCourseId(
        @ApiParam("利用返回的课程id传入")@RequestParam("id") Integer id
    ){
        List<Resource> resources = resourceService.list(new LambdaQueryWrapper<Resource>()
                .eq(Resource::getType,1)
                .eq(Resource::getUorrId,id)
                .orderByAsc(Resource::getUpdateTime));

        for (Resource resource : resources) {
            resource.setUrl(resourceService.getVideoUrlByUorrIdAndId(id,resource.getId()));
            resource.setTeacherName(resourceService.getTeacherNameByVideoId(resource.getUorrId()));
        }
        return R.success(resources);
    }

    @RequestRoles({"teacher"})
    @GetMapping("/getKindNames")
    @ApiOperation("c获取所有课程类别")
    public R<List<String>> getKindNames(){
            return R.success(kindService.getAllKindValue());
    }


    @RequestRoles({"teacher"})
    @GetMapping("/search")
    @ApiOperation("a多条件查询课程")
    public R<Page<Course>> search(
            @ApiParam("当前页")@RequestParam("pageCur") Integer pageCur,
            @ApiParam("页码")@RequestParam("pageSize") Integer pageSize,
        @ApiParam("课程名称")@RequestParam("name") String name,
        @ApiParam("开始时间")@RequestParam("startTime") String startTime,
        @ApiParam("结束时间")@RequestParam("endTime") String endTime,
        @ApiParam("课程类别名")@RequestParam("kindName") String kindName
    ){
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
        Integer teacherId = (Integer) request.getSession().getAttribute("id");
        wrapper.eq(Course::getTeacherId,teacherId);
        if(!name.equals("")){
            wrapper.like(Course::getCourseName,"%"+name+"%");
        }
        if(!startTime.equals("")){
            wrapper.gt(Course::getUpdateTime,startTime);
        }
        if(!endTime.equals("")){
            wrapper.lt(Course::getUpdateTime,endTime);
        }
        if(!kindName.equals("")){
            List<Integer> ids = kindService.getCourseIdsByKindName("%"+kindName+"%");
            if(!ids.isEmpty()){
                wrapper.in(Course::getId, ids);
            }
        }
        Page<Course> page = courseService.page(new Page<>(pageCur,pageSize),wrapper);
        for (Course course : page.getRecords()) {
            course.setTeacherName(courseService.getTeacherNameByTeacherId(course.getTeacherId()));
            course.setCoverImgUrl(resourceService.getCoverImgUrlByCourseId(course.getId()));
            course.setResponds(commentService.getCountByTypeAndLinkId(1,course.getId()));
            course.setKindName(kindService.getValueByCourseId(course.getId()));
        }
        return R.success(page);
    }

    @RequestRoles({"teacher"})
    @PutMapping("/setCourseImg")
    @ApiOperation("a更换课程封面")
    public R<String> setCourseImg(
        @ApiParam("封面图片")@RequestParam("img") MultipartFile img,
        @ApiParam("利用返回的课程id传入")@RequestParam("id") Integer id
        ){
        if(img==null||img.isEmpty()||!Objects.requireNonNull(img.getOriginalFilename()).contains(".")){
            return R.success("使用自动生成图片");
        }
        R<String> res = uploadUtil.uploadMedia(img, uploadPath + courseService.getDirPathByCourseId(id), UUID.randomUUID().toString());
        //删除原图片
        File file = new File(resourceService.getUploadImg(id));
        if(file.exists()){
            file.delete();
        }
        if(res.getCode()==1){
            resourceService.update(new LambdaUpdateWrapper<Resource>().eq(Resource::getUorrId,id).eq(Resource::getType,3).set(Resource::getUrl,res.getData())
                    .set(Resource::getUpdateTime,LocalDateTime.now().toString()));
            logservice.createLog("COURSE_IMG_UPDATE","update-img-"+request.getSession().getAttribute("username"),courseService.getCourseNameById(id));
        }
        return R.success(resourceService.getCoverImgUrlByCourseId(id));
    }

    @RequestRoles({"teacher"})
    @PostMapping("/updateCourse")
    @ApiOperation("a更新课程信息")
    public R<Course> updateCourse(
            @ApiParam("利用返回的课程id传入")@RequestParam("id") Integer id,
            @ApiParam("课程类型名称数组（可为空）")@RequestParam("kindNames") String[] kindNames,
            @ApiParam("课程名")@RequestParam("courseName") String courseName,
            @ApiParam("课程备注")@RequestParam("courseRemake") String courseRemake
    ){
        if(!request.getSession().getAttribute("id").equals(courseService.getTeacherIdByCourseId(id))){
            return R.err("用户不得修改非该用户创建课程");
        }
        LambdaUpdateWrapper<Course> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(Course::getId,id)
                .set(Course::getCourseName,courseName)
                .set(Course::getCourseRemake,courseRemake)
                .set(Course::getUpdateTime,LocalDateTime.now().toString());
        //课程类别更新
        kindService.remove(new LambdaQueryWrapper<Kind>().eq(Kind::getCourseId,id));
        for (String kindName : kindNames) {
            kindService.save(new Kind(kindName,id,LocalDateTime.now().toString(),courseService.getKindNameValueByKindName(kindName)));
        }
        //课程更新
        courseService.update(wrapper);
        Course newCourse = courseService.getById(id);
        newCourse.setTeacherName(courseService.getTeacherNameByTeacherId(courseService.getTeacherIdByCourseId(id)));
        newCourse.setCoverImgUrl(resourceService.getCoverImgUrlByCourseId(id));
        newCourse.setKindName(kindService.getValueByCourseId(newCourse.getId()));
        logservice.createLog("COURSE_UPDATE","update-course-"+request.getSession().getAttribute("username"),courseName);
        return R.success(newCourse);
    }


    @RequestRoles({"teacher"})
    @PostMapping("/createCourse")
    @ApiOperation("a创建课程(返回该课程数据)")
    public R<Course> createCourse(
            @ApiParam("课程名")@RequestParam("courseName") String courseName,
            @ApiParam("课程备注")@RequestParam("courseRemake") String courseRemake,
            @ApiParam("课程类型名称数组（可为空）")@RequestParam("kindNames") String[] kindNames
    ){
        Integer id = (Integer) request.getSession().getAttribute("id");//教师id
        String username = request.getSession().getAttribute("username").toString();
        if(courseService.existCourseByName(courseName,id)){
            return R.err("请勿创建相同课程");
        }
        //课程赋值
        Course course = new Course(courseName,id,courseRemake,LocalDateTime.now().toString(),LocalDateTime.now().toString());
        //创建课程
        courseService.save(course);
        //新建分类
            for (String kindName : kindNames) {
                kindService.save(new Kind(kindName,course.getId(),LocalDateTime.now().toString(),courseService.getKindNameValueByKindName(kindName)));
            }
        //新建课程文件夹
        File file = new File(uploadPath+id+"/"+course.getId());
        if (!file.exists()){
            file.mkdir();
        }
        //先默认生成一张图
        R<String> result =  uploadUtil.defaultImgByString(course.getCourseName(),uploadPath + id + "/" + course.getId() + "/", String.valueOf(course.getId()));
        resourceService.save(new Resource(3, course.getId(),result.getData(), LocalDateTime.now().toString(),LocalDateTime.now().toString()));
        logservice.createLog("COURSE_CREATE","create-course-"+username,course.getCourseName());
        Course returnCourse = courseService.getById(course.getId());
        returnCourse.setCoverImgUrl(resourceService.getCoverImgUrlByCourseId(course.getId()));
        returnCourse.setTeacherName(courseService.getTeacherNameByTeacherId(returnCourse.getTeacherId()));
        returnCourse.setKindName(kindService.getValueByCourseId(returnCourse.getId()));
        //创建课程话题中的一个基础话题
        Talk talk = new Talk("《"+courseName+"》的课程讨论区",courseRemake, id, LocalDateTime.now().toString(),1,course.getId());
        //创建话题
        talkService.save(talk);
        //添加到课程话题中
        talkService.insertUC(id,course.getId());
        return R.success(returnCourse);
    }

    @RequestRoles({"teacher"})
    @PostMapping("/uploadVs")
    @ApiOperation("b上传多个课程视频（视频大小不超过1GB）")
    public R<String> setCourseVideos(
        @ApiParam("课程id")@RequestParam("id")Integer id,
        @ApiParam("视频文件组")@RequestParam("files") MultipartFile[] files
    ) throws IOException {
        if(files.length==0){
            return R.err("请勿上传空文件");
        }
        for (MultipartFile file : files) {
            String uuid = String.valueOf(UUID.randomUUID());//设置文件名
            String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."));
            file.transferTo(new File(uploadPath + courseService.getDirPathByCourseId(id) + uuid + suffix));
            resourceService.save(new Resource(1, id, uuid + suffix, LocalDateTime.now().toString(), LocalDateTime.now().toString(), file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf(".")), resourceService.getEpisodesByUorrId(id)+1));
            courseService.updateCourseProgress(id,1);//课程进度+1
            logservice.createLog("TEACHER_UPLOAD","upload-course-"+id+"num-"+resourceService.getEpisodesByUorrId(id), "teacher-"+request.getSession().getAttribute("username"));
        }
        return R.success("上传成功！");
    }
    @RequestRoles({"teacher"})
    @PostMapping("/uploadVideo")
    @ApiOperation("b上传单个课程视频（视频大小不超过1GB）")
    public R<String> setCourseVideo(
            @ApiParam("课程id")@RequestParam("id")Integer id,
            @ApiParam("视频名称")@RequestParam("remake")String remake,
            @ApiParam("视频文件")@RequestParam("file") MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            return R.err("请勿提交空文件");
        }
        if (file.getSize() > 1024 * 1024 * 1024) {
            throw new RolePermissionException("单个文件大小超出1GB");
        }
        if(resourceService.getCountOfRemake(remake,id)>0){
            return R.err("该课程已有课程视频名称，请重新设置名称");
        }
        String uuid = String.valueOf(UUID.randomUUID());//设置文件名
        String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."));
        file.transferTo(new File(uploadPath + courseService.getDirPathByCourseId(id) + uuid + suffix));
        resourceService.save(new Resource(1, id, uuid + suffix, LocalDateTime.now().toString(), LocalDateTime.now().toString(), remake, resourceService.getEpisodesByUorrId(id)+1));
        courseService.updateCourseProgress(id,1);//课程进度+1
        logservice.createLog("TEACHER_UPLOAD","upload-course-"+id+"num-"+resourceService.getEpisodesByUorrId(id), "teacher-"+request.getSession().getAttribute("username"));
        return R.success("上传成功！");
    }
    @RequestRoles({"teacher"})
    @PutMapping("/setCourseState")
    @ApiOperation("a设置课程状态[0未完结，1已完结]")
    public R<String> setStateOfCourse(
            @ApiParam("课程id")@RequestParam("id")Integer id,
            @ApiParam("状态[0未完结，1已完结]")@RequestParam("state")Integer state
    ){
        courseService.update(new LambdaUpdateWrapper<Course>().eq(Course::getId,id)
                .set(Course::getState,state)
                .set(Course::getUpdateTime,LocalDateTime.now().toString()));
        if(state==1){
            logservice.createLog("COURSE_STATE_OVER","course-"+courseService.getCourseNameById(id),"课程完结");
        }else{
            logservice.createLog("COURSE_STATE_RESTART","course-"+courseService.getCourseNameById(id),"课程继续更新");
        }
        return R.success("修改成功");
    }
    @RequestRoles({"teacher"})
    @PutMapping("/updateVideo")
    @ApiOperation("b更新单个课程视频（视频大小不超过1GB）")
    public R<String> updateVideo(
            @ApiParam("资源id")@RequestParam("id")Integer id,
            @ApiParam("视频名称")@RequestParam("remake")String remake,
            @ApiParam("视频文件")@RequestParam("file") MultipartFile file){
        if (file.isEmpty()) {
            return R.err("请勿提交空文件");
        }
        if (file.getSize() > 1024 * 1024 * 1024) {
            throw new RolePermissionException("单个文件大小超出1GB");
        }
        if(resourceService.getCountOfRemake(remake,id)>=1){
            return R.err("该课程已有课程视频名称，请重新设置名称");
        }
        //获取原资源
        Resource one = resourceService.getOne(new LambdaQueryWrapper<Resource>().eq(Resource::getId, id));
        Integer courseId = resourceService.getUorrIdById(id);
        //上传视频
        R<String> r = uploadUtil.uploadMedia(file,uploadPath+courseService.getDirPathByCourseId(courseId),String.valueOf(UUID.randomUUID()));
        if(r.getCode()==1){
            //删除文件
            if(uploadUtil.deleteFile(uploadPath+courseService.getDirPathByCourseId(courseId)+one.getUrl()).getCode()==1){
                resourceService.update(new LambdaUpdateWrapper<Resource>().eq(Resource::getId,id)
                        .set(Resource::getUpdateTime,LocalDateTime.now().toString())
                        .set(Resource::getUrl,r.getData())
                        .set(Resource::getRemake,remake));
                logservice.createLog("TEACHER_UPDATE","update-video-"+request.getSession().getAttribute("username"),"");
                return R.success(resourceService.getVideoUrlByUorrIdAndId(courseId,id));
            }
        }
        return R.err("更新失败，请稍后再试");
    }

    @RequestRoles({"teacher"})
    @DeleteMapping("/deleteCourse")
    @ApiOperation("a删除单个课程")
    public R<String> deleteCourse(
            @ApiParam("课程id")@RequestParam("id")Integer id
    ){
        Course course = courseService.getById(id);
        Integer userId = (Integer) request.getSession().getAttribute("id");
        if(userId!=course.getTeacherId()){
            return R.err("无权限删除");
        }
        //先删除课程
        if(courseService.removeById(id)){
            //删课程封面
            resourceService.remove(new LambdaQueryWrapper<Resource>().eq(Resource::getType,3).eq(Resource::getUorrId,id));
            //再删除视频
            resourceService.removeByIds(resourceService.getIdsByCourseId(id));
            //删除课程文件夹
            File file = new File(uploadPath+userId+"/"+id);
            if(file.exists()){
                deleteFile(file);//删除子文件
                file.delete();//删除目录
            }
            //删除评分以及点赞和收藏
            commentService.remove(new LambdaQueryWrapper<Comment>().eq(Comment::getLinkId,id).eq(Comment::getType,1));
            praiseService.remove(new LambdaQueryWrapper<Praise>().eq(Praise::getType,3).eq(Praise::getTargetId,id));
            scoreService.remove(new LambdaQueryWrapper<CourseScore>().eq(CourseScore::getCourseId,id));
            collectService.remove(new LambdaQueryWrapper<Collect>().eq(Collect::getType,2).eq(Collect::getLinkId,id));
            //删除课程话题所有联系
            talkService.deleteUCT(course.getId());

            logservice.createLog("COURSE_DELETE","delete-course-"+request.getSession().getAttribute("username"),"");
            return R.success("删除成功");
        }
        return R.err("删除失败");
    }

    /**
     * 删除子文件
     * @param folder
     */
    private void deleteFile(File folder){
        File[] files = folder.listFiles();
        if (files!=null){
            for (File file : files) {
                if(file.isDirectory()){
                    deleteFile(file);
                }else{
                    file.delete();
                }
            }
        }
    }
    @RequestRoles({"teacher"})
    @DeleteMapping("/deleteVideo")
    @ApiOperation("b删除单个课程视频")
    public R<String> deleteVideo(
            @ApiParam("视频资源id")@RequestParam("id")Integer id
    ){
        Resource de = resourceService.getById(id);
        Integer courseId = resourceService.getUorrIdById(id);
        if(uploadUtil.deleteFile(uploadPath+courseService.getDirPathByCourseId(courseId)+de.getUrl()).getCode()==1) {
            //调整资源集数
            resourceService.adjustEpisodes(de.getEpisodes());
            //调整课程进度 -1
            courseService.updateCourseProgress(resourceService.getUorrIdById(id),-1);
            resourceService.removeById(id);
            //删除评论点赞
            commentService.remove(new LambdaQueryWrapper<Comment>().eq(Comment::getLinkId,id).eq(Comment::getType,2));
            praiseService.remove(new LambdaQueryWrapper<Praise>().eq(Praise::getType,4).eq(Praise::getTargetId,id));
            logservice.createLog("TEACHER_DELETE","delete-video-"+request.getSession().getAttribute("username"),"");
            return R.success("删除成功");
        }
        return R.err("删除失败");
    }


}
